package io.renren.modules.test1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.common.service.impl.CrudServiceImpl;
import io.renren.common.utils.ConvertUtils;
import io.renren.modules.test1.config.Config;
import io.renren.modules.test1.dao.ShowUserDao;
import io.renren.modules.test1.dto.ShowUserDTO;
import io.renren.modules.test1.entity.ShowUserEntity;
import io.renren.modules.test1.service.ShowUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0 2021-05-26
 */
@Service
public class ShowUserServiceImpl extends CrudServiceImpl<ShowUserDao, ShowUserEntity, ShowUserDTO> implements ShowUserService {

    @Autowired
    private ShowUserDao showUserDao;
    //记录用户查看过的信息,用户sessionID，新闻ID
    public final static Map<String, List<Long>> cacheMap = new HashMap();
    //记录用户查看数据库中的位置，数据库查询指针
    public final static Map<String, Integer> pointMap = new HashMap<>();
    //显示的缓存
    public Map<String, List<ShowUserDTO>> cacheShow = new HashMap();
    //增加观看统计  用户ID，数据分类，观看次数
    public Map<String, Map<String, Integer>> recommendCompute = new HashMap<>();


    /**
     * 进行推荐计算 共10个
     * 中意推荐 5个
     * 其他推荐 5个
     */
    private String getMax(HttpSession session) {
        Object attribute = session.getAttribute(Config.SESSION_KEEP);
        if (attribute == null) {
            return null;
        }
        Integer maxNum = 0;
        AtomicReference<String> maxType = new AtomicReference<>();
        Map<String, Integer> stringIntegerMap = recommendCompute.get(attribute);
        stringIntegerMap.forEach((k, v) -> {
            if (v > maxNum) {
                maxType.set(k);
            }
        });
        return maxType.get();
    }


    /**
     * 显示数据
     *
     * @param session
     * @return
     */
    public List<ShowUserDTO> show(HttpSession session) {
        //如果用户没session，创建
        Object attribute = session.getAttribute(Config.SESSION_KEEP);
        String id = null;
        if (attribute == null) {
            id = UUID.randomUUID().toString();
            session.setAttribute(Config.SESSION_KEEP, id);
        } else {
            id = (String) attribute;
        }
        if (!cacheMap.containsKey(id)) {//用户设置后没有查看过
            cacheMap.put(id, new ArrayList<>());
            pointMap.put(id, 0);
            cacheShow.put(id, new ArrayList<>());
            recommendCompute.put(id,new HashMap<>());
        }

        //如果需要显示的信息小于显示数量，进行数据库查询
        List<ShowUserDTO> showUserDTOList = cacheShow.get(id);
        if (showUserDTOList.size() < Config.SHOW_VOLUME) {
            //更新指针
            Integer integer = pointMap.get(id);
            pointMap.put(id, integer + Config.QUERY_DATA_VOLUME);
            //查询数据库信息，加入缓存
            List<ShowUserDTO> showUserDTOS = showUserDao.selectLimit(integer, Config.QUERY_DATA_VOLUME)
                    .stream()
                    .filter(showUserDTO -> !cacheMap.containsKey(showUserDTO.getId()))
                    .collect(Collectors.toList());

            showUserDTOList.addAll(showUserDTOS);
            cacheShow.put(id, showUserDTOList);
            show(session);
        }
        String maxType = getMax(session);
        //进行显示
        List<ShowUserDTO> collect = showUserDTOList.stream()
                .filter(showUserDTO -> showUserDTO.getShowType().equals(maxType))
                .limit(Config.SHOW_VOLUME / 2).collect(Collectors.toList());
        collect.addAll(showUserDTOList.stream().filter(showUserDTO -> !showUserDTO.getShowType().equals(maxType)).limit(Config.SHOW_VOLUME -collect.size()).collect(Collectors.toList()));
        return collect;
    }

    /**
     * 进行观看数据
     *
     * @param session
     * @param id
     * @return
     */
    @Override
    public List<ShowUserDTO> view(HttpSession session, Long id) {
        //查看缓存中是否存在此ID
        Object attribute = session.getAttribute(Config.SESSION_KEEP);
        if (attribute != null) {
            //遍历显示的缓存，然后进行剔除观看过的
            List<ShowUserDTO> showUserDTOS = cacheShow.get(attribute)
                    .stream()
                    .filter(showUserDTO -> {
                        if (showUserDTO.getId().equals(id)) {
                            //嵌入检测，统计看过的数据
                            Map<String, Integer> stringIntegerMap = recommendCompute.get(attribute);
                            Integer integer = stringIntegerMap.get(showUserDTO.getShowType());
                            stringIntegerMap.put(showUserDTO.getShowType(), integer==null? 1:integer+1);
                            recommendCompute.put((String) attribute, stringIntegerMap);

                            List<Long> longs = cacheMap.get(attribute);
                            longs.add(showUserDTO.getId());
                            cacheMap.put((String) attribute, longs);
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            cacheShow.put((String) attribute, showUserDTOS);
        }
        return show(session);
    }

    @Override
    public List<Long> history(HttpSession session) {
        Object attribute = session.getAttribute(Config.SESSION_KEEP);
        if (attribute == null) {
            return null;
        }
        return cacheMap.get(attribute);
    }

    /**
     * 找到用户查看的ID
     */
    private void viewdId(Long id) {

    }

    /**
     * 模拟数据，进行数据的模拟
     *
     * @param num
     * @return
     */
    public List mock(int num) {
        List<ShowUserEntity> list = new ArrayList<>();
        ShowUserDTO showUserDTO = new ShowUserDTO();
        Random random = new Random();
        for (int i = 0; i < num; i++) {
            showUserDTO.setShowType((Math.abs(random.nextInt()) % Config.CLASSIFICATION_NUMBER) + "");
            showUserDTO.setShowContext(UUID.randomUUID().toString());
            ShowUserEntity showUserEntry = ConvertUtils.sourceToTarget(showUserDTO, ShowUserEntity.class);
            showUserDao.insert(showUserEntry);
            list.add(showUserEntry);
        }
        return list;
    }

    @Override
    public String session(HttpSession session, String id) {
        String msg = null;
        String sessionKeep = (String) session.getAttribute(Config.SESSION_KEEP);
        session.setAttribute(Config.SESSION_KEEP, id);
        if (sessionKeep == null || sessionKeep.equals(id)) {
            msg = "success";
        } else {
            msg = "session 改变 由" + sessionKeep + " → " + id;
        }
        return msg;
    }

    @Override
    public QueryWrapper<ShowUserEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");

        QueryWrapper<ShowUserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);

        return wrapper;
    }


}